#include <zenilib.h>
#include "vector2.h"

Vector2::Vector2() 
{
    
}

Vector2::Vector2(float x_, float y_) 
{
	x = x_;
    y = y_;
}

Vector2::Vector2(const Vector2& v) 
{
	*this = v;
}

Vector2& Vector2::operator=(const Vector2& v)
{	
	x = v.x;
	y = v.y;
	return *this;
}

bool Vector2::operator==(const Vector2& v) const
{	
	return ((x == v.x) && (y == v.y));
}

bool Vector2::operator!= (const Vector2& v) const
{	
	return !( *this == v );
}

Vector2& Vector2::operator+=(const Vector2& v)
{
	x += v.x;
	y += v.y;
	return *this;
}		

Vector2& Vector2::operator-=(const Vector2& v)
{
	x -= v.x;
	y -= v.y;
	return *this;
}

Vector2& Vector2::operator*=(const float s)
{
	x *= s;
	y *= s;
	return *this;
}

Vector2& Vector2::operator/=(float s)
{
	x /= s;
	y /= s;
	return *this;
}

Vector2	operator+(const Vector2& v1, const Vector2& v2)
{	
	return Vector2(v1.x + v2.x, v1.y + v2.y);
}

Vector2	operator-(const Vector2& v1, const Vector2& v2)
{
	return Vector2(v1.x - v2.x, v1.y - v2.y);
}

float operator*(const Vector2& v1, const Vector2& v2)
{
	return (v1.x * v2.x) + (v1.y * v2.y);
}

float operator^	( const Vector2& v1, const Vector2& v2 )
{
	return (v1.x * v2.y) - (v1.y * v2.x);
}

Vector2	operator/(const Vector2& v1, const Vector2& v2)
{
	return Vector2 (v1.x / v2.x, v1.y / v2.y);
}

Vector2	operator*(const Vector2& v, const float s)
{
	return Vector2 (v.x * s, v.y * s);
}

Vector2	operator*(const float s, const Vector2& v)
{
	return v * s;
}

Vector2	multiply(const Vector2& v1, const Vector2& v2)
{
	return Vector2(v1.x * v2.x, v1.y * v2.y);
}

Vector2	operator/(const Vector2& v, const float s)
{
	return v * (1.0f / s) ;
}

Vector2	operator-(const Vector2& v)
{
	return Vector2 ( -v.x, -v.y );
}

void Vector2::swap(Vector2& other)
{
	Vector2 temp = *this;
	*this = other;
	other = temp;
}

Vector2 Vector2::normal()
{
    Vector2 t = *this;
    float len = length();
	if (len > 0.0f)
	{
    t.x = x/len;
    t.y = y/len;
	}
    return t;
}

void Vector2::normalize() 
{	
	*this = normal(); 	
}

Vector2 Vector2::perp() const
{
	return Vector2(-y, x);
}

Vector2 Vector2::reflectionOver(Vector2 & normal)
{
	return *this - (2 * normal * (*this * normal));
}

float Vector2::angle()
{
	if (x > 0){
		return -atan(y / x);
	}
	else if (x < 0){
		return 2 * pi - atan(y / x);
	}
	else{
		return y >= 0 ? 0 : pi;
	}
}

Vector2 Vector2::rotate(float theta)
{
	float cosTheta = cos(theta);
	float sinTheta = sin(theta);
	return Vector2(x * cosTheta - y * sinTheta, x * sinTheta + y * cosTheta);
}

Vector2& Vector2::transform(const Vector2& trans, float rot)
{
	Vector2 D = (*this).rotate(rot);
	*this = trans + D;
	return *this;
}

Vector2 Vector2::rotateAround(Vector2 & pt, float theta)
{
	return pt + (*this - pt).rotate(theta);
}

//float SmallAngleBetween(Vector2 &v1, Vector2 &v2)
//{
//	float d = DotProduct(v1.Abs().Normal(), v2.Abs().Normal());
//	if (d < -1){
//		return 0;
//	}
//	else if (d > 1){
//		return 0;
//	}
//	return acos(d);
//}

float AngleBetween(Vector2 &v1, Vector2 &v2)
{
	return (float)atan2(v1 ^ v2, v1 * v2);
}

////return intersection of lines segments defined by these points
//Vector2 Intersection(Vector2 &v1, Vector2 &v2, Vector2 &v3, Vector2 &v4)
//{
//	float ua = ((v4.x - v3.x)*(v1.y - v3.y) - (v4.y - v3.y)*(v1.x - v3.x)) / 
//			   ((v4.y - v3.y)*(v2.x - v1.x) - (v4.x - v3.x)*(v2.y - v1.y));
//	float x = v1.x + ua * (v2.x - v1.x);
//	float y = v1.y + ua * (v2.y - v1.y);
//	return Vector2(x, y);
//}
//
//int SideOfLine(Vector2 p, Vector2 p1, Vector2 p2)
//{
//	float side;
//	if (p1.x != p2.x){
//		side = p.y - p1.y - ((p2.y - p1.y) / (p2.x - p1.x)) * (p.x - p1.x);
//	}
//	else{
//		side = p.x - p1.x;
//	}
//	if (side > 0){
//		return 1;
//	}
//	else if (side == 0){
//		return 0;
//	}
//	else{
//		return -1;
//	}
//}

//float DistanceToLine(Vector2 p, Vector2 p1, Vector2 p2)
//{
//	float lineLength = Vector2(p2 - p1).Length();
//	if (lineLength == 0){ //ensure line segment points aren't equal
//		return Vector2(p1 - p).Length();
//	}
//	float distance = ((p2.x - p1.x)*(p1.y - p.y) - (p1.x - p.x)*(p2.y - p1.y)) / lineLength;
//	if (distance < 0){
//		return -distance;
//	}
//	return distance;
//}